package com.quectel.util.redis;

import com.quectel.util.client.redis.RedisClient;
import lombok.Getter;

import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.function.Supplier;

/**
 * <pre>
 *     本帮助类内置RedissonClient
 * </pre>
 *
 * @author caolu
 */
public class RedisUtils {

    @Getter
    private static RedisClient defaultClient;


    private RedisUtils() {

    }

    /**
     * 容器启动时设置一次即可
     *
     * @param defaultClient
     */
    public static void setDefaultClient(RedisClient defaultClient) {
        RedisUtils.defaultClient = defaultClient;
    }

    /**
     * 是否已经初始化配置
     *
     * @return
     */
    public static boolean isReady() {
        return RedisUtils.defaultClient != null;
    }


    /**
     * 设置一个key value
     *
     * @param key
     * @param value
     */
    @Deprecated
    public static void set(String key, String value) {
        defaultClient.set(key, value);
    }

    /**
     * 设置一个key携带有效期
     *
     * @param key
     * @param value
     * @param expirationTime
     * @param timeUnit
     */
    public static void set(String key, String value, long expirationTime, TimeUnit timeUnit) {
        defaultClient.set(key, value, expirationTime, timeUnit);
    }

    /**
     * 得到一个value
     *
     * @param key
     * @return
     */
    public static String get(String key) {
        return defaultClient.get(key);
    }

    /**
     * 设置一个对象携带有效期
     *
     * @param key
     * @param value          其实是把value转为json
     * @param expirationTime
     * @param timeUnit
     */
    public static void setObject(String key, Object value, long expirationTime, TimeUnit timeUnit) {
        defaultClient.setObject(key, value, expirationTime, timeUnit);
    }


    /**
     * 得到对象
     *
     * @param key
     * @param clazz 泛型
     */
    public static <T> T getObject(String key, Class<T> clazz) {
        return defaultClient.getObject(key, clazz);
    }

    /**
     * 序列化并存入
     *
     * @param key
     * @param value
     * @param expirationTime
     * @param timeUnit
     */
    public static void setBinaryObject(String key, Object value, long expirationTime, TimeUnit timeUnit) {
        defaultClient.setBinaryObject(key, value, expirationTime, timeUnit);
    }

    /**
     * 得到序列化对象
     *
     * @param key
     * @return
     */
    public static Object getBinaryObject(String key) {
        return defaultClient.getBinaryObject(key);
    }

    /**
     * key s1 zhang
     * key s2 wang
     * key s3 li
     *
     * @param key
     * @param hashKey
     * @param value
     * @param keyExpirationTime 大集合的过期时间
     * @param timeUnit
     */
    public static void hSet(String key, String hashKey, String value, long keyExpirationTime, TimeUnit timeUnit) {
        defaultClient.hSet(key, hashKey, value, keyExpirationTime, timeUnit);
    }

    /**
     * 通过key和hashKey得到一个值
     *
     * @param key
     * @param hashKey
     * @return
     */
    public static String hGet(String key, String hashKey) {
        return defaultClient.hGet(key, hashKey);
    }

    /**
     * 得到hset所有的hashKey 和 value
     *
     * @param key
     * @return key代表hashKey
     */
    public static Map<String, String> hGetAll(String key) {
        return defaultClient.hGetAll(key);
    }

    /**
     * 删除hashKey对应的值
     *
     * @param key
     * @param hashKeys
     */
    public static void hDel(String key, Object... hashKeys) {
        defaultClient.hDel(key, hashKeys);
    }

    /**
     * 判断一个key是否存在
     *
     * @param key
     * @return
     */
    public static Boolean exists(String key) {
        return defaultClient.exists(key);
    }

    /**
     * 删除指定的key
     *
     * @param key
     */
    public static void del(String key) {
        defaultClient.del(key);
    }

    /**
     * 模糊删除（慎用）
     * 模糊删除 a_* 就代表删除已a_开头的key *a_*删除包含a_的键
     *
     * @param key
     */
    public static void delFuzzy(String key) {
        defaultClient.delFuzzy(key);
    }

    /**
     * 给key设置有效期
     *
     * @param key
     * @param expirationTime
     * @param timeUnit
     */
    public static void expire(String key, long expirationTime, TimeUnit timeUnit) {
        defaultClient.expire(key, expirationTime, timeUnit);
    }

    /**
     * 得到key剩余的过期时间
     *
     * @param key
     * @param timeUnit
     * @return -2代表key不存在 -1代表key存在但是没有设置有效期
     */
    public static Long ttl(String key, TimeUnit timeUnit) {
        return defaultClient.ttl(key, timeUnit);
    }

    /**
     * 自增一个key 默认从0开始自增
     *
     * @param key
     * @param increment 每次自增多少
     * @return 自增后的值
     */
    public static long incr(String key, long increment) {
        return defaultClient.increment(key, increment);
    }

    /**
     * 自增设置有效期 已经实现原子性  <br>
     * 对于double的值尽量转为long然后自增 因为redis浮点型自增精度会丢失
     *
     * @param key
     * @param increment
     * @param expirationTime
     * @param timeUnit
     * @return
     */
    public static Long incr(String key, long increment, long expirationTime, TimeUnit timeUnit) {
        return defaultClient.increment(key, increment, expirationTime, timeUnit);
    }

    /**
     * 循环自增设置有效期 已经实现原子性  <br>
     * 对于double的值尽量转为long然后自增 因为redis浮点型自增精度会丢失
     *
     * @param key
     * @param increment      支持负数
     * @param min
     * @param max
     * @param expirationTime
     * @param timeUnit
     * @return
     */
    public static Long loopIncr(String key, long increment, long min, long max, long expirationTime, TimeUnit timeUnit) {
        return defaultClient.loopIncrement(key, increment, min, max, expirationTime, timeUnit);
    }

    /**
     * @param key
     * @param hashKey
     * @return
     */
    public static long hIncr(String key, String hashKey) {
        return defaultClient.hIncrement(key, hashKey, 1);
    }

    /**
     * @param key
     * @param hashKey
     * @param increment
     * @return
     */
    public static long hIncr(String key, String hashKey, long increment) {
        return defaultClient.hIncrement(key, hashKey, increment);
    }

    /**
     * 得到redis时间
     *
     * @return
     */
    public static Long getRedisCurrentMillis() {
        return defaultClient.getRedisCurrentMillis();
    }

    /**
     * setnx函数 key存在返回false 不设置有效期慎用
     * set name 1 px 100000 nx
     *
     * @param key
     * @param value
     * @return
     */
    @Deprecated
    public static Boolean setnx(String key, String value) {

        return defaultClient.setNX(key, value);
    }

    /**
     * setnx函数 key存在返回false key不存在返回true
     * set name 1 px 100000 nx
     *
     * @param key
     * @param value
     * @param expirationTime
     * @param timeUnit
     * @return
     */
    public static Boolean setnx(String key, String value, long expirationTime, TimeUnit timeUnit) {

        return defaultClient.setNX(key, value, expirationTime, timeUnit);
    }

    /**
     * 获取分布式锁
     *
     * @param lockKey
     * @return RedisLock
     */
    public static Lock getDistributedLock(String lockKey) {

        return defaultClient.getDistributedLock(lockKey);

    }

    /**
     * 快速加锁方法
     *
     * @param lockKey
     * @param supplier
     * @param <T>
     * @return
     */
    public static <T> T doInDistributedLock(String lockKey, Supplier<T> supplier) {
        return defaultClient.doInDistributedLock(lockKey, supplier);
    }

    /**
     * @param lockKey
     * @return
     */
    public static Lock getSpinLock(String lockKey) {
        return defaultClient.getSpinLock(lockKey);

    }

    /**
     * 快速加锁方法
     *
     * @param lockKey
     * @param supplier
     * @param <T>
     * @return
     */
    public static <T> T doInSpinLock(String lockKey, Supplier<T> supplier) {
        return defaultClient.doInSpinLock(lockKey, supplier);
    }

    /**
     * 同时锁定多个key
     *
     * @param keys
     * @return
     */
    public static Lock getMultiSpinLock(String... keys) {
        return defaultClient.getMultiSpinLock(keys);
    }

    /**
     * set里边添加值
     *
     * @param key
     * @param values
     */
    public static void sAdd(String key, Set<String> values, long expirationTime, TimeUnit timeUnit) {
        defaultClient.sAdd(key, values, expirationTime, timeUnit);
    }

    /**
     * 取出set的值
     *
     * @param key
     */
    public static Set<String> members(String key) {
        return defaultClient.members(key);
    }

}
